<?php
/**
 * Lớp hỗ trợ Cache dữ liệu
 * @author Mr.UBKey
 *
 */
class XPHP_Cache {

  var $id;
  var $data;
  var $log;
  var $dir;
  var $filename;
  var $login_page;
 
  /**
   * Phương thức khởi tạo
   * @param bool $login_required
   */ 
  function __construct($login_required=false) {
    $this->log = "session() called<br />";
    $ret = true;
    
    /**
     * Dữ liệu được lưu trữ trong Cache
     * @var array
     */
    $this->data = array();
    
    /**
     * Nếu Cache yêu cầu login mà người dùng chưa login đưa về trang này
     */
    $this->login_page = "login.php";

    /**
     * Thư mục lưu trữ các file cache có dấu / cuối cùng
     * @var string
     */
    $this->dir = realpath("./")."/cache/";

    if ($this->exists()) {
      $this->log .= "sid: ".$this->id."<br />";
      if (!$this->load()) {
        /**
         * Không load được session cũ
         */
        $this->log .= "Could not restore session.<br />";
        $ret = true;
      }
    } else {
      if (!$this->newId()) {
      	/**
      	 * Không tạo được session mới
      	 */
        $this->log .= "Could not create new session.<br />";
        $ret = false;
      }
      $this->log .= "sid: ".$this->id."<br />";
    }
    
    if ($login_required) {
      $this->log .= "Require login requested<br />";
      if (!$this->data['logged_in']) {
        $this->log .= "Not logged in, redirecting to "
          .$this->login_page."<br />"; 
        $this->data['page_destination'] = $_SERVER['SCRIPT_NAME'];
        $this->save();
        header("Location: ".$this->login_page);
      }
    }
    return $ret;
  }
  
  /**
   * Xóa toàn bộ các thông tin trong session
   * Xóa file session
   */
  function expire() {
    $this->log .= "expire() called<br />";
    $ret = true;
    $this->data = array();
    if (!file_exists($this->filename)) {
      $this->log .= $this->filename." does not exist.<br />";
      $ret = false;
    } else {
      if (!@unlink($this->filename)) {
        $this->log .= "session file delete failed for "
          .$this->filename."<br />";
        $ret = false;
      }
    }
    if (!setcookie('sid' ,$this->id, time()-3600, "/")) {
      $this->log .= "sid cookie expire failed. This may be due to browser"
        ." output started prior.<br />";
      $ret = false;
    }
    return $ret;
  }

  /**
   * Kiểm tra xem sid cookie có trong máy người dùng không. Nếu không set id
   */
  function exists() {
    $this->log .= "exists() called<br />";
    if (!isset($_COOKIE['sid'])) {
      $this->log .= "sid cookie does not exist.<br />";
      return false;
    }
    $this->id = $_COOKIE['sid'];
    $this->filename = $this->dir."sid_".$this->id;
    return true;
  }

  /**
   * Tạo 32 kí tự phân biệt lưu vào cookie trình duyệt
   */
  function newId() {
    $this->log .= "newId() called<br />";
    $this->id = md5(uniqid(rand(), true));
    $this->filename = $this->dir."sid_".$this->id;
    if (!setcookie('sid' ,$this->id, null, "/")) {
      $this->log .= "sid cookie save failed. This may be due to browser"
        ." output started prior or the user has disabled cookies.<br />";
      return false;
    }
    return true;
  }
  
  /**
   * Đọc dữ liệu Session từ tệp tin
   */
  function load() {
    $this->log .= "load() called<br />";
    if (!file_exists($this->filename)) {
      $this->log .= $this->filename." does not exist.<br />";
      return false;
    }
    if (!$x = @file_get_contents($this->filename)) {
      $this->log .= "Could not read ".$this->filename."<br />";
      return false;
    }
    if (!$this->data = unserialize($x)) {
      $this->log .= "unserialize failed<br />";
      $this->data = array();
      return false;
    }
    return true;
  }

  /**
   * Lưu dữ liệu Session vào file để chia sẻ giữa các trang
   */
  function save() {
    $this->log .= "save() called<br />";
    if (count($this->data) < 1) {
      $this->log .= "Nothing to save.<br />";
      return false;
    }
    //create file pointer
    if (!$fp=@fopen($this->filename,"w")) {
      $this->log .= "Could not create or open ".$this->filename."<br />";
      return false;
    }
    //write to file
    if (!@fwrite($fp,serialize($this->data))) {
      $this->log .= "Could not write to ".$this->filename."<br />";
      fclose($fp);
      return false;
    }
    //close file pointer
    fclose($fp);
    return true;
  }

  /**
   * Xóa toàn bộ các Session
   * @param int $minutes
   */
  function cleanAll($minutes) {
    $this->log .= "cleanAll() called to delete sessions older than "
      .$minutes." minutes<br />";
    chdir($this->dir);
    $ret = shell_exec("find -type f -name 'sid_*' -maxdepth 1 -mmin +".$minutes.' -exec rm -f {} \;');
  }
  
}